#!/usr/bin/perl -w
#-------------------------------------------------------+
#                                                       |
# MAIZE BIN PLOT                                        |
#                                                       |
#-------------------------------------------------------+
#  AUTHOR: James C. Estill                              |
# CONTACT: jestill_at_sourceforge.net                   |
# STARTED: 4/4/2006                                     |
# UPDATED: 4/5/2006                                     |
#                                                       |
# DESCRIPTION:                                          |
#  Given an input file of the maize bin data to map     |
#  create a colored choropleth map.                     |       
#                                                       |
# REQUIRES:                                             |
#  -$MaizePNGData - Path to PNG file to of chromosome   |
#                   bins to serve as template image     |
#  -$MaizeData -    Path to the text file that contains |
#                   a white space delimitted file with  | 
#                   the data to plot in the form of:    |
#                     Chrom Bin X Y Z                   |
#                   Example                             |
#                     1 0 11 7                          |
#                     1 0 11 21                         |
#                                                       |
# USAGE:                                                |
#                                                       |
#-------------------------------------------------------+

print "The Maize Bin Plot program has started\n";

#-------------------+
# INCLDUES          |
#-------------------+
use GD;
use GD::Graph;
use GD::Graph::points;
GD::Graph::colour;

#-------------------+
# LOCAL VARIABLES   |
#-------------------+
my $MaizeJPGPath = "/home/jestill/hmpr_msll/images/maize_bins.jpg";
my $MaizePNGPath = "/home/jestill/hmpr_msll/images/maize_bins_bw.png";
my(@zmBins,@GraphData); # The zmBins array will hold the data from the zea bins
my (@GraphData1,@GraphData2,@GraphData3,@GraphData4,
    @XVals,@XVals1,@XVals2,@XVals3,@XVals4,
    @YVals, @YVals1, @YVals2, @YVals3, @YVals4, 
    $MaxXValue,$MaxYValue);
#my $MaizeData = "/home/jestill/hmpr_msll/scripts/zmBinData.txt";
#my $MaizeData = "/home/jestill/hmpr_msll/scripts/zmBinDataMites.txt";
my $MaizeData = "/home/jestill/hmpr_msll/scripts/zmBinDataMsll.txt";

my $GraphOut = "/home/jestill/hmpr_msll/scripts/Graph_MSLL.png";
my $BinMapOut = "/home/jestill/hmpr_msll/scripts/Bin_Map_MSLL.png";

#-------------------+
# LOAD DATA INTO AN |
# ARRAY SORTED BY Z |
#-------------------+
# ASSUMES DATA ARE WHITE SPACE DELIMITTED
# This could also be linked to output from 
# a MySQL DBI Reference
# Text file for now to get this working
# that is delim by space characters.
open (BINDATA, $MaizeData);
while (<BINDATA>)
{
    push @zmBins, [ split ];
}
my $NumRecords = $#zmBins;

# Try to sort the array by the z value
# This will allow for drawing the graph and
# quartiles 
@zmBins = sort { $a->[4] <=> $b->[4] } @zmBins;

# The Max Z Value will be used later to deterimine
# The max y value for the graph that will be
# drawn.
my $MinZValue = $zmBins[0][4];
my $MaxZValue = $zmBins[99][4];

#-------------------+
# MAIN PROGRAM      |
#-------------------+

# CHOROPLETH MAP OF MAIZE BINS
# SIZE IS 200,240
my $im = GD::Image->newFromPng ( $MaizePNGPath );

# GRAPH OF THE 
my $graph = GD::Graph::points->new (400, 300);

my $ComboImage = new GD::Image(640,300);

#-------------------+
# ALLOCATE COLORS   |
#-------------------+
$white = $im->colorAllocate(255,255,255);
$black = $im->colorAllocate(0,0,0);       
$red = $im->colorAllocate(255,0,0);      
$blue = $im->colorAllocate(0,0,255);
$green = $im->colorAllocate(0,255,0);
$gray = $im->colorAllocate(100,100,100);

# ALLOCATE SOME RED COLORS FOR A HEAT MAP
$red01 = $im->colorAllocate(50,0,0); 
$red02 = $im->colorAllocate(255,204,204);
$red03 = $im->colorAllocate(255,102,102);
$red04 = $im->colorAllocate(255,0,0);
$red05 = $im->colorAllocate(100,0,0);

# Same colors as used in GD::Graph
$JamieGray  = $im->colorAllocate (100, 100, 100);
$JamieWhite = $im->colorAllocate (255, 255, 255);
$JamiePink  = $im->colorAllocate (255, 204, 205);
$JamieRed   = $im->colorAllocate (255, 0, 0);
$DarkRed    = $im->colorAllocate (139, 0, 0);

#-------------------+
# DO SOME WORK WITH |
# THE GRAPH         |
#-------------------+
# The data array will need to be fetched from the results
# that are being mapped on the chromosomes, and the data 
# will need to be ordered. To show the 'accumulation'
# curve. An early test of these results could at first be
# showing gene density mapped on the chromosome set as
# determined by the annotation

# load data from input array to format for viewing in the 
# graph


# Can push data into different Y value sets so that 
# these can be drawn on the graph in different colors
# For variable num Y this could be done as an
# array of arrays. Where main array is numCategories
# long and the different Y val arrays would then 
# be just push@YVals[CatNum]
# Problem then becomes working with the colors
for ($i = 0; $i <= $NumRecords; $i++)
{
    print $i."\t".$zmBins[$i][4]."\n";
    push @XVals, $i + 1; 

    if ($i < 25) 
    {
	push @YVals1, $zmBins[$i][4];
	push @YVals2, undef;
	push @YVals3, undef;
	push @YVals4, undef;

    }
    elsif ($i < 50)
    {
	push @YVals1, undef;
	push @YVals2, $zmBins[$i][4];
	push @YVals3, undef;
	push @YVals4, undef;
    }
    elsif ($i < 75)
    {
	push @YVals1, undef;
	push @YVals2, undef;
	push @YVals3, $zmBins[$i][4];
	push @YVals4, undef;
    }
    else
    {
	push @YVals1, undef;
	push @YVals2, undef;
	push @YVals3, undef;
	push @YVals4, $zmBins[$i][4];
    }

}

my @GraphData = ( \@XVals, \@YVals1, \@YVals2, \@YVals3, \@YVals4 );

# FOR A SET NUMBER
#add_colour(colourname => [$r, $g, $b])
#$r = "255";
#$g = "0";
#$b = "0";

GD::Graph::colour::add_colour(JamieGray => [100, 100, 100]);
GD::Graph::colour::add_colour(JamieWhite => [255, 255, 255]);
GD::Graph::colour::add_colour(JamiePink => [255, 204, 205]);
GD::Graph::colour::add_colour(JamieRed => [255, 0, 0]);
GD::Graph::colour::add_colour(DarkRed => [139, 0, 0]);
$graph->set( 
	     x_label           => 'Maize Bin Rank',
	     y_label           => 'Gene Density',
#	     title             => 'Maize Bin Data Accumulation',
	     title             => 'Maize MSLL Hit Data Accumulation',
	     transparent       => 0, # 0 is false, default is transparent
	     markers           => [7], # 8 is empty circle, 9 is filled circle
	     marker_size       => 2,   # Size in points
#	     dclrs             => [qw (green blue red black) ],
	     dclrs             => [qw ( JamieWhite JamiePink JamieRed DarkRed) ],
	     bgclr             => JamieGray,
	     x_label_skip      =>10,
	     x_min_value       =>0,
	     x_max_value       =>100,
	     y_max_value       =>$MaxZValue,
	     y_tick_number     => 8,
	     y_label_skip      => 2 
	     ) or die $graph->error;


my $gd = $graph->plot(\@GraphData) or die $graph->error;


$png_data = $gd->png;
#open (DISPLAY,"| display -") || die;
#binmode DISPLAY;
#print DISPLAY $png_data;
#close DISPLAY;

#-------------------+
# COLOR IN THE      |
# CHROMOSOME BIN    |
# AND SHOW OUTCOME  |
#-------------------+

# make the background transparent and interlaced
#$im->transparent($white);
$im->interlaced('true');

# Fill in the background with gray
# to make easier on the eyes
$im->fill(1,1,$gray);


# QUICK AND DIRTY QUARTILE METHOD
# Just draw in order since the array
# is sorted by the z value after it
# has been loaded into the array.

# Fill the bins with test colors
for ($i = 0; $i <= $NumRecords; $i++)
{
    # Will perhaps need to select from different
    # colors here for the classified draw

    # The quick and dirty quartile method
    # since there are 100 bins
    # A more general quantile method could be used where
    # C = number of categories to create
    # N = number of bins to split into quantiles
    
    if ($i < 25) 
    {
	$im->fill($zmBins[$i][2],$zmBins[$i][3],$JamieWhite);
#	$im->fill($zmBins[$i][2],$zmBins[$i][3],$green);
    }
    elsif ($i < 50)
    {
	$im->fill($zmBins[$i][2],$zmBins[$i][3],$JamiePink);
#	$im->fill($zmBins[$i][2],$zmBins[$i][3],$blue);
    }
    elsif ($i < 75)
    {
	$im->fill($zmBins[$i][2],$zmBins[$i][3],$JamieRed);
#	$im->fill($zmBins[$i][2],$zmBins[$i][3],$red);
    }
    else
    {
	$im->fill($zmBins[$i][2],$zmBins[$i][3],$DarkRed);
#	$im->fill($zmBins[$i][2],$zmBins[$i][3],$black);
    }

}

# Get the background color index
# This assumes that background color is
# homogenous and that the pixel at 
# 1,1, is representative.
$BackColor = $im->getPixel(1,1);
#print STDOUT $BackColor \n;

# Print the image to the screen for test
# on the linux box this uses the image magick
# program.
$png_data = $im->png;

#open (DISPLAY,"| display -") || die;
#binmode DISPLAY;
#print DISPLAY $png_data;
#close DISPLAY;

#-------------------+
# SHOW THE DATA     |
# TOGETHER          |
#-------------------+

# CHOROPLETH MAP OF MAIZE BINS
# SIZE IS 200,240
#my $im = GD::Image->newFromPng ( $MaizePNGPath );
#my $graph = GD::Graph::points->new (400, 300);
#my $ComboImage = new GD::Image(600,600);


$ComboImage->copy($im,0,0,0,0,200,240);
$ComboImage->copy($gd,220,0,0,0,400,300);

$combo_png = $ComboImage->png;
open (DISPLAY,"| display -") || die;
binmode DISPLAY;
print DISPLAY $combo_png;
close DISPLAY;

# dATA AS PngS
#$gd is the graph data
#$png_data is the chrom bin data


exit;

#-------------------------------------------------------+
# SUBFUNCTIONS                                          |
#-------------------------------------------------------+
# Given N classes, and an array need subfunctions for
# - Color Selection
# - Classification
#   - Quantile Method
#   - Equal Interval

#-------------------------------------------------------+
# HISTORY                                               |
#-------------------------------------------------------+
#
# 4/5/2006
# - Program started
# - Worked with GD to open and fill basemap image
# - Worked witg GD::Graph to draw dummy data
# - Created a black and white maize bin base map 
# - Checked that XY positions for all 100 bins properly
#   color the Maize Bins Basemap
# 4/5/2006
# - Allowed for input from text file
# - Doing quartile by ranking on Z Value
# - Plotting Real Data with color code
#   on the x-y plot
# - Plotting Read Data with color code
#   on the chromosomes
# - Combined outcome to a single image
